package com.ruoyi.team.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.team.domain.Goods;
import com.ruoyi.team.service.IGoodsService;
import com.ruoyi.team.vo.GoodsCategoryTreeSelect;
import org.apache.regexp.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.team.mapper.GoodsCategoryMapper;
import com.ruoyi.team.domain.GoodsCategory;
import com.ruoyi.team.service.IGoodsCategoryService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 物品分类信息Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-28
 */
@Service
public class GoodsCategoryServiceImpl extends ServiceImpl<GoodsCategoryMapper, GoodsCategory> implements IGoodsCategoryService {

    @Autowired
    private IGoodsService goodsService;

    /**
     * 查询物品分类信息列表
     *
     * @param goodsCategory 物品分类信息
     * @return 物品分类信息
     */
    @Override
    public List<GoodsCategory> selectGoodsCategoryList(GoodsCategory goodsCategory) {
        return getBaseMapper().selectGoodsCategoryList(goodsCategory);
    }

    /**
     * 新增分类
     * @param entity 新增分类节点
     * @return 是否成功
     */
    @Override
    public boolean save(GoodsCategory entity) {
        getBaseMapper().insert(entity);
        // 获取到父节点的分类层级结构,并拼接子分类的id, 设置到子分类的分类层级结构
        GoodsCategory goodsCategory = getBaseMapper().selectById(entity.getParentId());
        entity.setBusiPath(goodsCategory.getBusiPath() + ":" + entity.getId());

        return getBaseMapper().updateById(entity) > 0;
    }

    /**
     * 修改
     * @param entity 修改分类对象
     * @return 是否修改成功
     */
    @Override
    public boolean updateById(GoodsCategory entity) {
        // 获取到父节点的分类层级结构,并拼接子分类的id, 设置到子分类的分类层级结构
        GoodsCategory goodsCategory = getBaseMapper().selectById(entity.getParentId());
        entity.setBusiPath(goodsCategory.getBusiPath() + ":" + entity.getId());

        return getBaseMapper().updateById(entity) > 0;
    }

    /**
     * 删除分类时连同子分类一起删除
     * 删除分类时如当前分类连同子分类下的商品还有库存则不可以删
     * @param list 需要删除的 id
     * @return 返回成功或者失败
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        // 查询需要删除的 分类
        List<GoodsCategory> goodsCategories = getBaseMapper().selectBatchIds((Collection<? extends Serializable>) list);

        for (GoodsCategory goodsCategory : goodsCategories) {

            ArrayList<Goods> goods = new ArrayList<>();
            // 查询需要删除的分类的子分类
            List<GoodsCategory> goodsCategories1 = getBaseMapper().selectGoodsCategoryByParentId(goodsCategory.getId());
            if (goodsCategories1.size() > 0){
                // 查询子分类下是否有商品
                for (GoodsCategory category : goodsCategories1) {
                    List<Goods> goods1 = goodsService.selectGoodsListByCategoryId(category.getId());
                    goods.addAll(goods1);
                }
            }
            // 查询该分类下是否有商品
            goods.addAll(goodsService.selectGoodsListByCategoryId(goodsCategory.getId()));
            if (goods.size() > 0){
                throw new RuntimeException("该分类或者该分类的子类下有商品");
            }

            // 删除该分类的子分类
            getBaseMapper().deleteGoodsCategoryByParentId(goodsCategory.getId());
            // 删除该分类
            getBaseMapper().deleteById(goodsCategory.getId());
        }
        return true;
    }
    /**
     * 构建前端所需要下拉树结构
     *
     * @param goodsCategoryList 物品分类列表
     * @return 下拉树结构列表
     */
    @Override
    public List<GoodsCategoryTreeSelect> buildDeptTreeSelect(List<GoodsCategory> goodsCategoryList) {
        List<GoodsCategory> deptTrees = buildDeptTree(goodsCategoryList);
        return deptTrees.stream().map(GoodsCategoryTreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 构建前端所需要树结构
     *
     * @param goodsCategoryList 物品分类列表
     * @return 树结构列表
     */
    @Override
    public List<GoodsCategory> buildDeptTree(List<GoodsCategory> goodsCategoryList) {
        // 结果表
        List<GoodsCategory> returnList = new ArrayList<>();

        // 存储ID 的临时列表
        List<Long> tempList = new ArrayList<>();
        // 所有物品分类信息ID 存入临时表
        for (GoodsCategory goodsCategory : goodsCategoryList) {
            tempList.add(goodsCategory.getId());
        }

        for (GoodsCategory goodsCategory : goodsCategoryList) {

            // 判断是否为顶级节点(顶级节点的ID为0, 并且其他的ID不能为0)
            if (!tempList.contains(goodsCategory.getParentId())) {
                // 得到子节点
                recursionFn(goodsCategoryList, goodsCategory);
                // 遍历该父节点的所有子节点
                returnList.add(goodsCategory);
            }
        }
        // 如果 结果表为空 ==> 所有节点都是顶级节点
        if (returnList.isEmpty()) {
            returnList = goodsCategoryList;
        }

        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<GoodsCategory> list, GoodsCategory goodsCategory) {
        // 得到子节点列表
        List<GoodsCategory> childList = getChildList(list, goodsCategory);

        goodsCategory.setChildren(childList);

        for (GoodsCategory goodsCategoryChild : childList) {
            if (hasChild(list, goodsCategoryChild))
            {
                recursionFn(list, goodsCategoryChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<GoodsCategory> getChildList(List<GoodsCategory> list, GoodsCategory goodsCategory) {
        List<GoodsCategory> goodsCategoryList = new ArrayList<>();

        for (GoodsCategory n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == goodsCategory.getId().longValue()) {
                goodsCategoryList.add(n);
            }
        }
        return goodsCategoryList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<GoodsCategory> list, GoodsCategory t) {
        return getChildList(list, t).size() > 0;
    }


    /**
     * 分类迁移
     * @return 是否更新了该分类以及子分类
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean migrate(Long sourceId, Long targetId, boolean subtype){

        // 查询被迁移分类是否有子类
        List<GoodsCategory> goodsCategories = getBaseMapper().selectGoodsCategoryByParentId(sourceId);
        // 定义子分类的受影响行数
        int progeny = 0;
        // 如果有子分类
        if (goodsCategories.size() > 0){
            // 需要迁移子分类
            if (subtype){
                return this.updateParent(sourceId, targetId) > 0;

            }
            // 不需要迁移子分类
            else {
                // 查询出需要修改的分类对象
                GoodsCategory sourceGoodsCategory = getBaseMapper().selectById(sourceId);
                for (GoodsCategory goodsCategory : goodsCategories) {
                    // 将父分类的父id设置为子分类的父id
                    goodsCategory.setParentId(sourceGoodsCategory.getParentId());
                    // 将子分类的id层级结构中的 父id + : 替换为空
                    goodsCategory.setBusiPath(goodsCategory.getBusiPath().replace(sourceId + ":", ""));
                    // 将更新后的子分类更新到数据库
                    progeny = getBaseMapper().updateById(goodsCategory);
                }

                // 迁移父类
                // 查询出目标对象
                GoodsCategory targetGoodsCategory = getBaseMapper().selectById(targetId);
                // 将目标分类的id设置为源分类的父id
                sourceGoodsCategory.setParentId(targetId);
                // 在目标分类的id层级结构后拼接上 :sourceId
                sourceGoodsCategory.setBusiPath(targetGoodsCategory.getBusiPath() + ":" + sourceId);
                // 将修改后的 源分类 更新到数据库中
                int parent = getBaseMapper().updateById(sourceGoodsCategory);

                // 判断父分类和子分类是否都更新了
                return (parent > 0 && progeny > 0);
            }
        }

        // 没有子分类时,修改分类
        // 查询出需要修改的分类对象
        GoodsCategory sourceGoodsCategory = getBaseMapper().selectById(sourceId);
        // 查询出目标对象
        GoodsCategory targetGoodsCategory = getBaseMapper().selectById(targetId);
        // 将目标分类的id设置为源分类的父id
        sourceGoodsCategory.setParentId(targetId);
        // 在目标分类的id层级结构后拼接上 :sourceId
        sourceGoodsCategory.setBusiPath(targetGoodsCategory.getBusiPath() + ":" + sourceId);
        // 将修改后的 源分类 更新到数据库中
        int parent = getBaseMapper().updateById(sourceGoodsCategory);

        return parent > 0;
    }


    // 递归修改分类及子分类
    private int updateParent(Long sourceId, Long targetId){
        // 查询出需要修改的分类对象
        GoodsCategory sourceGoodsCategory = getBaseMapper().selectById(sourceId);
        // 查询出目标对象
        GoodsCategory targetGoodsCategory = getBaseMapper().selectById(targetId);
        // 将目标分类的id设置为源分类的父id
        sourceGoodsCategory.setParentId(targetId);
        // 在目标分类的id层级结构后拼接上 :sourceId
        sourceGoodsCategory.setBusiPath(targetGoodsCategory.getBusiPath() + ":" + sourceId);
        // 将修改后的 源分类 更新到数据库中
        int i = getBaseMapper().updateById(sourceGoodsCategory);

        List<GoodsCategory> goodsCategories = getBaseMapper().selectGoodsCategoryByParentId(sourceId);
        if (goodsCategories.size() > 0){
            for (GoodsCategory goodsCategory : goodsCategories) {
                this.updateParent(goodsCategory.getId(), goodsCategory.getParentId());
            }
        }
        return i;
    }

}
